//
//  MainViewController.swift
//  XMGWB
//
//  Created by xiaomage on 15/11/6.
//  Copyright © 2015年 xiaomage. All rights reserved.
//

import UIKit

class MainViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        
        // 0.添加自定义加号按钮到tabBar
        tabBar.addSubview(composeButton)
        
        // 1.计算按钮的宽度
        let width = tabBar.bounds.width / CGFloat(childViewControllers.count)
        let height = composeButton.bounds.height
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        
        // 2.调整加号按钮位置
        composeButton.frame = CGRectOffset(rect, 2 * width, 0)
    }
    
    // MARK: - 内部控制方法
    /// 监听加号按钮点击
    @objc private func composeBtnClick(){
        
        /*
        UITextField
        不可以换行
        不可以滚动
        可以显示占位提示文本  placeholder
        
        UITextView
        可以换行
        可以滚动
        不可以显示占位提示文本
        */
        let sb = UIStoryboard(name: "ComposeViewController", bundle: nil)
        let vc = sb.instantiateInitialViewController()!
        presentViewController(vc, animated: true, completion: nil)
        
    }
    
    // MARK: - 懒加载
    private lazy var composeButton: UIButton = {
        let btn = UIButton(imageName: "tabbar_compose_icon_add", backgroundImage: "tabbar_compose_button")
        btn.addTarget(self, action: Selector("composeBtnClick"), forControlEvents: UIControlEvents.TouchUpInside)
        
        return btn
    }()
}


// MARK: - 其他

 //// ////////////////////////////////

class MainView {
    
//    override func viewDidLoad() {
//        super.viewDidLoad()
//        
//        // iOS7以后只需要设置tintColor, 那么图片和文字都会按照tintColor渲染
//        tabBar.tintColor = UIColor.orangeColor()
//        
//        // 添加子控制器
//        addChildViewControllers()
//    }
    
    /// 添加所有子控制器
    func addChildViewControllers()
    {
        /*
        addChildViewController(HomeTableViewController(), title: "首页", imageName: "tabbar_home")
        addChildViewController(MessageTableViewController(), title: "消息", imageName: "tabbar_message_center")
        addChildViewController(DiscoverTableViewController(), title: "发现", imageName: "tabbar_discover")
        addChildViewController(ProfileTableViewController(), title: "我", imageName: "tabbar_profile")
        */
        
        addChildViewController("HomeTableViewController", title: "首页", imageName: "tabbar_home")
        addChildViewController("MessageTableViewController", title: "消息", imageName: "tabbar_message_center")
        addChildViewController("DiscoverTableViewController", title: "发现", imageName: "tabbar_discover")
        addChildViewController("ProfileTableViewController", title: "我", imageName: "tabbar_profile")
    }
    
    /// 添加一个子控制器
    //    func addChildViewController(childController: UIViewController, title: String, imageName: String) {
    
    func addChildViewController(childControllerName: String, title: String, imageName: String) {
        
        /*
        guard 条件表达式 else {
        //            需要执行的语句
        //            只有条件为假才会执行{}中的内容
        return
        }
        guard可以有效的解决可选绑定容易形成if{}else{}嵌套问题
        */
        
        // 1.动态获取命名空间   // 通过String ->Class -->创建对象
        // 由于字典/数组中只能存储对象, 所以通过一个key从字典中获取值取出来是一个AnyObject类型, 并且如果key写错或者没有对应的值, 那么就取不到值, 所以返回值可能有值也可能没值, 所以最终的类型是AnyObject?
        guard let name =  NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as? String else
        {
            NJLog("获取命名空间失败")
            return
        }
        /*
        Swift中新增了一个叫做命名空间的概念
        作用: 避免重复
        不用项目中的命名空间是不一样的, 默认情况下命名空间的名称就是当前项目的名称
        正是因为Swift可以通过命名空间来解决重名的问题, 所以在做Swift开发时尽量使用cocoapods来集成三方框架, 这样可以有效的避免类名重复
        正是因为Swift中有命名空间, 所以通过一个字符串来创建一个类和OC中也不太一样了, OC中可以直接通过类名创建一个类,
        而Swift中如果想通过类名来创建一个类必须加上命名空间
        */
        let cls: AnyClass? = NSClassFromString(name + "." + childControllerName)
        
        // Swift中如果想通过一个Class来创建一个对象, 必须告诉系统这个Class的确切类型
        guard let typeCls = cls as? UITableViewController.Type else
        {
            NJLog("cls不能当做UITableViewController")
            return
        }
        
        // 通过Class创建对象
        let childController = typeCls.init()
        NJLog(childController)
        
        /*
        // 1.2设置自控制的相关属性
        childController.title = title
        childController.tabBarItem.image = UIImage(named: imageName)
        childController.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted")
        
        
        // 1.3包装一个导航控制器
        let nav = UINavigationController(rootViewController: childController)
        // 1.4将子控制器添加到UITabBarController中
        addChildViewController(nav)
        */
    }
}

//
//  MainViewController.swift
//  XMGWB
//
//  Created by xiaomage on 15/12/1.
//  Copyright © 2015年 xiaomage. All rights reserved.
//


class MainViewC {
    
//    override func viewDidLoad() {
//        super.viewDidLoad()
//        
//        // iOS7以后只需要设置tintColor, 那么图片和文字都会按照tintColor渲染
//        tabBar.tintColor = UIColor.orangeColor()
//        
//        // 添加子控制器
//        addChildViewControllers()
//    }
//    
    /// 添加所有子控制器
    func addChildViewControllers()
    {
        
        // 1.根据JSON文件创建控制器
        // 1.1读取JSON数据
        guard let filePath =  NSBundle.mainBundle().pathForResource("MainVCSettings.json", ofType: nil) else
        {
            NJLog("JSON文件不存在")
            return
        }
        
        guard let data = NSData(contentsOfFile: filePath) else
        {
            NJLog("加载二进制数据失败")
            return
        }
        
        // 1.2将JSON数据转换为对象(数组字典)
        do
        {
            /*
            Swift和OC不太一样, OC中一般情况如果发生错误会给传入的指针赋值, 而在Swift中使用的是异常处理机制
            1.以后但凡看大 throws的方法, 那么就必须进行 try处理, 而只要看到try, 就需要写上do catch
            2.do{}catch{}, 只有do中的代码发生了错误, 才会执行catch{}中的代码
            3. try  正常处理异常, 也就是通过do catch来处理
               
               try!
                    告诉系统一定不会有异常, 也就是说可以不通过 do catch来处理
                    但是需要注意, 开发中不推荐这样写, 一旦发生异常程序就会崩溃
                    如果没有异常那么会返回一个确定的值给我们
            
              try?  告诉系统可能有错也可能没错, 如果没有系统会自动将结果包装成一个可选类型给我们, 
                    如果有错系统会返回nil, 如果使用try? 那么可以不通过do catch来处理
            */
            
            let objc = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! [[String: AnyObject]]
            //   [[String: AnyObject]]  字典数组
            // 1.3遍历数组字典取出每一个字典
            for dict in objc
            {
                // 1.4根据遍历到的字典创建控制器
                let title = dict["title"] as? String
                let vcName = dict["vcName"] as? String
                let imageName = dict["imageName"] as? String
                addChildViewController(vcName, title: title, imageName: imageName)
            }
        }catch
        {
            // 只要try对应的方法发生了异常, 就会执行catch{}中的代码
            addChildViewController("HomeTableViewController", title: "首页", imageName: "tabbar_home")
            addChildViewController("MessageTableViewController", title: "消息", imageName: "tabbar_message_center")
            addChildViewController("DiscoverTableViewController", title: "发现", imageName: "tabbar_discover")
            addChildViewController("ProfileTableViewController", title: "我", imageName: "tabbar_profile")
        }
    }
    
    /// 添加一个子控制器
    func addChildViewController(childControllerName: String?, title: String?, imageName: String?) {
        
        
        // 1.动态获取命名空间
        guard let name =  NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as? String else
        {
            NJLog("获取命名空间失败")
            return
        }
        
        // 2.根据字符串获取Class
        var cls: AnyClass? = nil
        if let vcName = childControllerName
        {
            cls = NSClassFromString(name + "." + vcName)
        }
        
        // 3.根据Class创建对象
        // Swift中如果想通过一个Class来创建一个对象, 必须告诉系统这个Class的确切类型
        guard let typeCls = cls as? UITableViewController.Type else
        {
            NJLog("cls不能当做UITableViewController")
            return
        }
        // 通过Class创建对象
        let childController = typeCls.init()
        
        
        // 1.2设置自控制的相关属性
        childController.title = title
        if let ivName = imageName
        {
            childController.tabBarItem.image = UIImage(named: ivName)
            childController.tabBarItem.selectedImage = UIImage(named: ivName + "_highlighted")
        }
        
//        // 1.3包装一个导航控制器
//        let nav = UINavigationController(rootViewController: childController)
//        // 1.4将子控制器添加到UITabBarController中
//        addChildViewController(nav)
        
    }
    
    /*
    public : 最大权限, 可以在当前framework和其他framework中访问
    internal : 默认的权限, 可以在当前framework中随意访问
    private : 私有权限, 只能在当前文件中访问
    以上权限可以修饰属性/方法/类
    
    在企业开发中建议严格的控制权限, 不想让别人访问的东西一定要private
    */
    // 如果给按钮的监听方法加上private就会报错, 报错原因是因为监听事件是由运行循环触发的, 而如果该方法是私有的只能在当前类中访问
    // 而相同的情况在OC中是没有问题, 因为OC是动态派发的        //出门时没带钱，买东西时，先赚钱，再买
    // 而Swift不一样, Swift中所有的东西都在是编译时确定的     //出门时 带钱，买东西时，直接买
    // 如果想让Swift中的方法也支持动态派发, 可以在方法前面加上 @objc
    // 加上 @objc就代表告诉系统需要动态派发
    @objc private func compseBtnClick(btn: UIButton)
    {
        NJLog(btn)
    }
    // MARK: - 懒加载
    private lazy var composeButton: UIButton = {
        () -> UIButton
        in
        // 1.创建按钮
        let btn = UIButton()
        // 2.设置前景图片
        btn.setImage(UIImage(named: "tabbar_compose_icon_add"), forState: UIControlState.Normal)
        btn.setImage(UIImage(named: "tabbar_compose_icon_add_highlighted"), forState: UIControlState.Highlighted)
        // 3.设置背景图片
        btn.setBackgroundImage(UIImage(named: "tabbar_compose_button"), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: "tabbar_compose_button_highlighted"), forState: UIControlState.Highlighted)
        
        // 4.监听按钮点击
        btn.addTarget(self, action: Selector("compseBtnClick:"), forControlEvents: UIControlEvents.TouchUpInside)
        // 4.调整按钮尺寸
        btn.sizeToFit()
        
        return btn
    }()

}
